/*
 *
 * すべての関数で戻り値がー１の場合は、他のアプリケーションが
 * デバイスを使用中のためコマンドガ失敗しています。
 * 正常な場合は、０をかえします。
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <fcntl.h>
#include <time.h>
#include <io.h>


static char packet[16];
enum {
    iRESET,iBREAK,iRUN,MPEEK,MPOKE,KPEEK,KPOKE,VPEEK,VPOKE,
    APEEK,APOKE,APEEKP,APOKEP,CPEEK,CPOKE,GETPUT,ADDRESS
  };

#if defined(__WATCOMC__)&&defined(__386__)
#define IOCTL_MAX 0x2000
#else
#define IOCTL_MAX 0x4000
#endif

/*-----------------------------------------------------------------
 *
 *  Reset 後のウェイト
 *
 */
void _sleep(int sec)
{
    time_t tm;
    while(sec-- > 0){
	tm = time(0);
	while( tm == time(0));
    }
}

/*-----------------------------------------------------------------
 *
 * ＰＣ−ＦＸＧのリセット
 * 
 * fh    :デバイスハンドル
 */
int pio_reset(int fh)
{
    packet[0] = iRESET;
    *(long *)(packet+1) = 0L;
    if(ioctl(fh,3,packet,5)<5) return -1;
    _sleep(2);
    return 0;
}

/*-----------------------------------------------------------------
 *
 * ＰＣーＦＸＧへ割り込みを発生する
 *
 * fh    :デバイスハンドル
 */
int pio_break(int fh)
{
    packet[0] = iBREAK;
    *(long *)(packet+1) = 0L;
    return (ioctl(fh,3,packet,5)<5)? -1:0;
}

/*-----------------------------------------------------------------
 *
 * 指定アドレスからプログラムを実行する
 *
 * fh    :デバイスハンドル
 * adr   :Ｖ８１０アドレス
 */
int pio_run(int fh,unsigned long adr)
{
    packet[0] = iRUN;
    *(long *)(packet+1) = 0L;
    *(long *)(packet+5) = adr;
    return (ioctl(fh,3,packet,9)<9)? -1:0;
}

/*-----------------------------------------------------------------
 *
 *
 *
 */
static int pio_peek(int fh,int cmd,unsigned long adr,long len,char *buf)
{
    int i,slen;

    packet[0] = cmd&0xff;
    *(long *)(packet+1) = len;
    *(long *)(packet+5) = adr;
    if (ioctl(fh,3,packet,9)<9) return -1;
    while(len) {
	slen = (len >= (long)IOCTL_MAX)? IOCTL_MAX:(int)len;
	if (ioctl(fh,2,buf,slen)<slen) return -1;
	buf += slen;
	len -= slen;
    }
    return 0;
}


/*-----------------------------------------------------------------
 *
 * 
 *
 */
static int pio_poke(int fh,int cmd,unsigned long adr,long len,char *buf)
{
    int i,slen;

    packet[0] = cmd&0xff;
    *(long *)(packet+1) = len;
    *(long *)(packet+5) = adr;

    if( ioctl(fh,3,packet,9)<9) return -1;
    while(len) {
	slen = (len >= (long)IOCTL_MAX)? IOCTL_MAX:(int)len;
	if (ioctl(fh,3,buf,slen)<slen) return -1;
	buf += slen;
	len -= slen;
    }
    return 0;
}

/*-----------------------------------------------------------------
 *
 * Ｖ８１０ＲＡＭをホストへ転送する
 *
 * fh     :デバイスハンドル
 * adr    :Ｖ８１０アドレス
 * len    :バイトレングス
 * buf    :バッファポインタ
 *
 */
int pio_mpeek(int fh,unsigned long adr,long len,char *buf)
{
    return pio_peek(fh,MPEEK, adr,len,(char *)buf);
}

/*-----------------------------------------------------------------
 *
 * ホストからＶ８１０ＲＡＭへ転送する
 *
 * fh     :デバイスハンドル
 * adr    :Ｖ８１０アドレス
 * len    :バイトレングス
 * buf    :バッファポインタ
 *
 */
int pio_mpoke(int fh,unsigned long adr,long len,char *buf)
{
    return pio_poke(fh,MPOKE, adr,len, (char *)buf);
}

/*-----------------------------------------------------------------
 *
 * ＨｕＣ６２７２ＲＡＭをホストへ転送する
 *
 * fh     :デバイスハンドル
 * adr    :ＨｕＣ６２７２アドレス
 * len    :ハーフワードレングス
 * buf    :バッファポインタ
 *
 */
int pio_kpeek(int fh,unsigned long adr,long len,short *buf)
{
    return pio_peek(fh,KPEEK, adr,len*2,(char *)buf);
}

/*-----------------------------------------------------------------
 *
 * ホストからＨｕＣ６２７２ＲＡＭへ転送する
 *
 * fh     :デバイスハンドル
 * adr    :ＨｕＣ６２７２アドレス
 * len    :ハーフワードレングス
 * buf    :バッファポインタ
 *
 */
int pio_kpoke(int fh,unsigned long adr,long len,short *buf)
{
    return pio_poke(fh,KPOKE, adr,len*2,(char *)buf);
}

/*-----------------------------------------------------------------
 *
 * ＨｕＣ６２７０ＲＡＭをホストへ転送する
 *
 * fh     :デバイスハンドル
 * adr    :ＨｕＣ６２７０アドレス
 * len    :ハーフワードレングス
 * buf    :バッファポインタ
 *
 */
int pio_vpeek(int fh,unsigned long adr,long len,short *buf)
{
    return pio_peek(fh,VPEEK, adr,len*2,(char *)buf);
}

/*-----------------------------------------------------------------
 *
 * ホストからＨｕＣ６２７０ＲＡＭへ転送する
 *
 * fh     :デバイスハンドル
 * adr    :ＨｕＣ６２７０アドレス
 * len    :ハーフワードレングス
 * buf    :バッファポインタ
 *
 */
int pio_vpoke(int fh,unsigned long adr,long len,short *buf)
{
    return pio_poke(fh,VPOKE, adr,len*2,(char *)buf);
}

/*-----------------------------------------------------------------
 *
 * オーロラテクスチャバッファをホストへ転送する
 *
 * fh     :デバイスハンドル
 * adr    :オーロラアドレス
 * len    :ハーフワードレングス
 * buf    :バッファポインタ
 *
 */
int pio_apeek(int fh,unsigned long adr,long len,short *buf)
{
    return pio_peek(fh,APEEK, adr,len*2,(char *)buf);
}

/*-----------------------------------------------------------------
 *
 * ホストからオーロラテクスチャバッファへ転送する
 *
 * fh     :デバイスハンドル
 * adr    :オーロラアドレス
 * len    :ハーフワードレングス
 * buf    :バッファポインタ
 *
 */
int pio_apoke(int fh,unsigned long adr,long len,short *buf)
{
    return pio_poke(fh,APOKE, adr,len*2,(char *)buf);
}

/*-----------------------------------------------------------------
 *
 * オーロラテクスチャバッファをパックモードでホストへ転送する
 *
 * fh     :デバイスハンドル
 * adr    :オーロラパックモードアドレス
 * len    :ハーフワードレングス
 * buf    :バッファポインタ
 *
 */
int pio_apeekp(int fh,unsigned long adr,long len,short *buf)
{
    return pio_peek(fh,APEEKP, adr,len*2,(char *)buf);
}

/*-----------------------------------------------------------------
 *
 * ホストからパックモードでオーロラテクスチャバッファへ転送する
 *
 * fh     :デバイスハンドル
 * adr    :オーロラパックモードアドレス
 * len    :ハーフワードレングス
 * buf    :バッファポインタ
 *
 */
int pio_apokep(int fh,unsigned long adr,long len,short *buf)
{
    return pio_poke(fh,APOKEP, adr,len*2,(char *)buf);
}

/*-----------------------------------------------------------------
 *
 * ＨｕＣ６２６１ＲＡＭをホストへ転送する
 *
 * fh     :デバイスハンドル
 * adr    :ＨｕＣ６２６１アドレス
 * len    :ハーフワードレングス
 * buf    :バッファポインタ
 *
 */
int pio_cpeek(int fh,unsigned long adr,long len,short *buf)
{
    return pio_peek(fh,CPEEK, adr,len*2,(char *)buf);
}

/*-----------------------------------------------------------------
 *
 * ホストからＨｕＣ６２６１ＲＡＭへ転送する
 *
 * fh     :デバイスハンドル
 * adr    :ＨｕＣ６２６１アドレス
 * len    :ハーフワードレングス
 * buf    :バッファポインタ
 *
 */
int pio_cpoke(int fh,unsigned long adr,long len,short *buf)
{
    return pio_poke(fh,CPOKE, adr,len*2,(char *)buf);
}

/*-----------------------------------------------------------------
 *
 * fh     :デバイスハンドル
 * len    :レングス
 * buf    :バッファポインタ
 *
 */
int pio_get(int fh,long len,char *buf)
{
    int i,slen;

    packet[0] = GETPUT;
    *(long *)(packet+1) = len;
    if (ioctl(fh,3,packet,5)<5) return -1;
    while(len) {
	slen = (len >= (long)IOCTL_MAX)? IOCTL_MAX:(int)len;
	if (ioctl(fh,2,buf,slen)<slen) return -1;
	buf += slen;
	len -= slen;
    }
    return 0;
}

/*-----------------------------------------------------------------
 *
 * fh     :デバイスハンドル
 * len    :レングス
 * buf    :バッファポインタ
 *
 */
int pio_put(int fh,long len,char *buf)
{
    int i,slen;

    packet[0] = GETPUT;
    *(long *)(packet+1) = len;
    if (ioctl(fh,3,packet,5)<5) return -1;
    while(len) {
	slen = (len >= (long)IOCTL_MAX)? IOCTL_MAX:(int)len;
	if (ioctl(fh,3,buf,slen)<slen) return -1;
	buf += slen;
	len -= slen;
    }
    return 0;
}

int pio_address(int fh,short *buf)
{
    int i,slen;

    packet[0] = ADDRESS;
    if (ioctl(fh,3,packet,1)<1) return -1;
    if (ioctl(fh,2,buf,14)<14) return -1;
    return 0;
}

int pio_stat(int fh)
{
    unsigned char buf[1];

    if (ioctl(fh,2,buf,1)<1) return -1; /* BIOS mode */
    return buf[0];
}

/* EOF */
